/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package control;

import java.io.File;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;
import model.Province;
import model.SeaArea;
import model.Zone;
import model.Card;
import tools.Coord;
import vinciappli.CardId;
import vinciappli.ProvinceSubType;
import vinciappli.StaticParams;

/**
 *
 * @author JC
 */
public class ControllerXML
{

    public static final ControllerXML INSTANCE = new ControllerXML();
    private Document document;
    private Element racine;

    public ControllerXML()
    {
    }

    public void iniXML()
    {
        this.zones();
        this.cartes();
    }

    private void zones()
    {
        SAXBuilder sxb = new SAXBuilder();
        try
        {
            this.document = sxb.build(new File(StaticParams.XML_NOM_FICHIER_ZONES));
        }
        catch(Exception e)
        {
            System.out.println("Le fichier n'existe pas");
            e.printStackTrace();
        }
        racine = document.getRootElement();
        List listZones = racine.getChildren("zone");

        Iterator i = listZones.iterator();
        while(i.hasNext())
        {
            Element courant = (Element) i.next();
            //System.out.println(courant.getName()+" : "+courant.getAttributeValue("type"));
            // Cas d'une zone décrivant une province
            if(courant.getAttributeValue("type").compareTo("province") == 0)
            {
                this.memoriserZones(courant, StaticParams.XML_ZONE_EST_PROVINCE);
            }
            else
            {
                this.memoriserZones(courant, StaticParams.XML_ZONE_EST_MER);
            }
        }
        // System.out.println("Passage aux adjacences");
        listerAdjacence(listZones);
    }

    private void memoriserZones(Element courant, int typeZone)
    {
        List temp = courant.getChildren();
        Iterator i = temp.iterator();

        int num = 0;
        String fieldType = "";
        Set<ProvinceSubType> sousType = new HashSet<ProvinceSubType>();
        Map<String, Integer> occupationTerritoire = new HashMap<String, Integer>();
        Coord coord = new Coord();

        while(i.hasNext())
        {
            courant = (Element) i.next();

            if(courant.getName().compareTo(StaticParams.XML_BALISE_NUM) == 0)
            {
                num = Integer.parseInt(courant.getValue());
                //System.out.println("\t"+courant.getName()+" : "+num);
            }
            else if(courant.getName().compareTo(StaticParams.XML_BALISE_TERRAIN) == 0)
            {
                fieldType = courant.getValue();
                //System.out.println("\t"+courant.getName()+" : "+fieldType);
            }
            else if(courant.getName().compareTo(StaticParams.XML_BALISE_SOUSTYPE) == 0)
            {
                sousType.add(ProvinceSubType.valueOf(courant.getValue()));
                //System.out.println("\t"+courant.getName()+" : "+courant.getValue());
            }
            else if(courant.getName().compareTo(StaticParams.XML_BALISE_COORD) == 0)
            {
                List c = courant.getChildren();

                Iterator j = c.iterator();
                while(j.hasNext())
                {
                    Element crd = (Element) j.next();
                    if(crd.getName().compareTo(StaticParams.XML_BALISE_X) == 0)
                    {
                        coord.setX(Integer.parseInt(crd.getValue()));
                    }
                    else if(crd.getName().compareTo(StaticParams.XML_BALISE_Y) == 0)
                    {
                        coord.setY(Integer.parseInt(crd.getValue()));
                    }
                }
            }

        }

        switch(typeZone)
        {
            case StaticParams.XML_ZONE_EST_PROVINCE:
                Province newProvince = new Province(num, fieldType, sousType, occupationTerritoire, coord);

                try
                {
                    ControllerPrincipal.getINSTANCE().getControllerGameBoard().getGameBoard().getProvinces().add(newProvince);
                    // TO DO
                }
                catch(NullPointerException e)
                {
                    System.out.println(e.getMessage());
                }
                break;

            case StaticParams.XML_ZONE_EST_MER:
                SeaArea newSeaArea = new SeaArea(num, coord);
                ControllerPrincipal.getINSTANCE().getControllerGameBoard().getGameBoard().getSeaAreas().add(newSeaArea);
                break;
        }
    }

    private void listerAdjacence(List listZones)
    {
        Iterator i = listZones.iterator();
        while(i.hasNext())
        {
            Element courant = (Element) i.next();
            // System.out.println("Courant : "+courant.getName());
            // System.out.println("Num : "+courant.getChild("num").getValue());
            if(courant.getChild("adjacence") != null)
            {
                int typeZone;
                if(courant.getAttributeValue("type").compareTo("province") == 0)
                {
                    typeZone = StaticParams.XML_ZONE_EST_PROVINCE;
                }
                else
                {
                    typeZone = StaticParams.XML_ZONE_EST_MER;
                }
                creerAdjacence(courant.getChild("adjacence"), Integer.parseInt(courant.getChild("num").getValue()), typeZone);
            }
        }
    }

    private void creerAdjacence(Element courant, int num, int typeZone)
    {
        Set<SeaArea> nextToSea = new HashSet<SeaArea>();
        Set<Province> nextToProvince = new HashSet<Province>();
        Element tempEle;
        Zone zone = rechercherZone(num, typeZone);

        //System.out.println("Num de la zone : "+num);
        List listAdj = null;
        try
        {
            listAdj = courant.getChildren();
        }
        catch(NullPointerException e)
        {
            System.out.println(e.getMessage());
        }
        Iterator i = listAdj.iterator();
        while(i.hasNext())
        {
            tempEle = (Element) i.next();
            // System.out.println("type : "+tempEle.getAttributeValue("type") + " et num : "+tempEle.getValue());

            if(tempEle.getAttributeValue("type").compareTo(StaticParams.XML_ZONE_ADJ_PROVINCE) == 0)
            {
                try
                {
                    if(Integer.parseInt(tempEle.getValue()) == StaticParams.GAMEBOARD_EDGE_ID)
                    {
                        if(typeZone == StaticParams.XML_ZONE_EST_PROVINCE)
                        {
                            ControllerPrincipal.getINSTANCE().getControllerGameBoard().getGameBoard().getGameBoardEdge().getNearbyProvinces().add((Province)zone);
                        }
                        else if(typeZone == StaticParams.XML_ZONE_EST_MER)
                        {
                            ControllerPrincipal.getINSTANCE().getControllerGameBoard().getGameBoard().getGameBoardEdge().getNearbySeaAreas().add((SeaArea)zone);
                        }
                    }
                    nextToProvince.add((Province) rechercherZone(Integer.parseInt(tempEle.getValue()), StaticParams.XML_ZONE_EST_PROVINCE));
                }
                catch(NullPointerException e)
                {
                    System.out.println("N'existe pas - Province");
                }
            }
            else if(tempEle.getAttributeValue("type").compareTo(StaticParams.XML_ZONE_ADJ_MER) == 0)
            {
                try
                {
                    nextToSea.add((SeaArea) rechercherZone(Integer.parseInt(tempEle.getValue()), StaticParams.XML_ZONE_EST_MER));
                }
                catch(NullPointerException e)
                {
                    System.out.println("N'existe pas - Province");
                }
            }
            //System.out.println("\t"+courant.getName()+" Valeur : "+courant.getValue() +" et Type : "+courant.getAttributeValue("type"));
        }

        zone.setNearbyProvinces(nextToProvince);
        zone.setNearbySeaAreas(nextToSea);
    }

    private Zone rechercherZone(int numero, int typeZone)
    {
        switch(typeZone)
        {
            case StaticParams.XML_ZONE_EST_PROVINCE:
                Set<Province> listeProvinces = ControllerPrincipal.getINSTANCE().getControllerGameBoard().getGameBoard().getProvinces();
                for(Province province : listeProvinces)
                {
                    if(province.getNum() == numero)
                    {
                        return province;
                    }
                }
                break;

            case StaticParams.XML_ZONE_EST_MER:
                Set<SeaArea> listeSeaAreas = ControllerPrincipal.getINSTANCE().getControllerGameBoard().getGameBoard().getSeaAreas();
                for(SeaArea seaArea : listeSeaAreas)
                {
                    if(seaArea.getNum() == numero)
                    {
                        return seaArea;
                    }
                }
                break;
        }
        return null;
    }

    private void cartes()
    {
        SAXBuilder sxb = new SAXBuilder();
        try
        {
            this.document = sxb.build(new File(StaticParams.XML_NOM_FICHIER_CARTE));
        }
        catch(Exception e)
        {
            System.out.println("Le fichier n'existe pas");
            e.printStackTrace();
        }
        racine = document.getRootElement();
        List listZones = racine.getChildren("carte");

        Iterator i = listZones.iterator();
        while(i.hasNext())
        {
            Element courant = (Element) i.next();
            this.creerCarte(courant);
        }
    }

    private void creerCarte(Element courant)
    {

        boolean declin = Boolean.parseBoolean(courant.getAttributeValue("declin"));
        int nb = Integer.parseInt(courant.getChild("exemplaires").getValue());
        int pions = Integer.parseInt(courant.getChild("pions").getValue());
        CardId type;
        if(declin)
        {
            type = CardId.valueOf(courant.getChild("nom").getValue() + "Dec");
        }
        else
        {
            type = CardId.valueOf(courant.getChild("nom").getValue());
        }

        for(int i = 1; i <= nb; i ++)
        {
            this.enregistrerCarte(declin, pions, type);
        }
    }

    private void enregistrerCarte(boolean declin, int pions, CardId type)
    {
        Card carte = new Card(type, pions, declin);
        try
        {
            ControllerPrincipal.getINSTANCE().getControllerGameBoard().getGameBoard().getBag().getListCards().add(carte);
        }
        catch(Exception e)
        {
            System.out.println("erreur lors de l 'ajout d'une carte -- XML to Memoire");
        }
    }

    public static ControllerXML getINSTANCE()
    {
        return INSTANCE;
    }
}
